<template>
  <div class="print-wrap" v-if="showPrint">
    <div class="print-main">
      <div class="btn-wrap">
        <van-button type="info" @click="searchDevices('')" :disabled="btnDisabled">{{ btnText }}</van-button>
        <van-button type="info" plain @click="close">取消</van-button>
      </div>
      <div style="margin: 15px 0">
        已配对蓝牙:
        <ul id="matchDevice">
          <van-cell v-for="(item, index) in matchDeviceList" :key="index" :title="item.name" @click="handlePrint(item.id, index)">
            <template #right-icon>
              <van-loading type="spinner" v-if="item.isConnecting" />
              <van-icon name="success" v-if="item.isConnected" />
              <span v-if="!item.isConnected && !item.isConnecting" style="color: #ccc">未连接</span>
            </template>
          </van-cell>
        </ul>
      </div>
      <div>
        未配对蓝牙:
        <ul id="unmatchDevice">
          <van-cell v-for="(item, index) in unmatchDeviceList" :key="index" :title="item.name" @click="searchDevices(item.id, index)">
            <template #right-icon>
              <van-loading type="spinner" v-if="item.isConnecting" />
            </template>
          </van-cell>
        </ul>
      </div>
    </div>
  </div>
</template>

<script>
// let scan = null
export default {
  props: {
    printValue: {
      type: Array,
      defalut() {
        return []
      }
    },
    address: {
      type: String,
      default: ''
    },
    showPrint: {
      type: Boolean,
      defalut: false
    }
  },
  name: 'BluetoothMatch',
  data() {
    return {
      device: null,
      BAdapterL: null,
      BluetoothAdapter: null,
      uuid: null,
      main: null,
      bluetoothSocket: null,
      BleDevice: null,
      matchDeviceList: [],
      unmatchDeviceList: [],
      btnText: '搜索设备',
      btnDisabled: false,
      lastIndex: -1, //上一个链接的设备
      matchAddress: [],
      unmatchAddress: [],
      isMatching: false, //配对设备
      isConnecting: false, //连接设备打印
      isArray: false
    }
  },
  async mounted() {
    // setTimeout(() => {
    this.openBluetoothAdapter()
    console.log('print mounted---------------')
    if (JSON.parse(localStorage.getItem('matchDeviceList'))) {
      this.matchDeviceList = JSON.parse(localStorage.getItem('matchDeviceList'))
    }
    if (JSON.parse(localStorage.getItem('matchAddress'))) {
      this.matchAddress = JSON.parse(localStorage.getItem('matchAddress'))
    }
    console.log(this.matchDeviceList)
    // }, 500)
  },
  watch: {
    'matchDeviceList.length': {
      handler(newVal) {
        localStorage.setItem(
          'matchDeviceList',
          JSON.stringify(this.matchDeviceList)
        )
      }
    },
    'matchAddress.length': {
      handler(newVal) {
        localStorage.setItem('matchAddress', JSON.stringify(this.matchAddress))
      }
    }
  },
  methods: {
    // 监听蓝牙设备连接状态
    listenerConnection() {
      plus.bluetooth.onBLEConnectionStateChange(function (e) {
        console.log('connection state changed: ' + JSON.stringify(e))
      })
    },
    openBluetoothAdapter() {
      console.log('初始化蓝牙模块--------')
      var _this = this
      plus.bluetooth.openBluetoothAdapter({
        success: function (e) {
          console.log('open success: ' + JSON.stringify(e))
        },
        fail: function (e) {
          console.log('open failed: ' + JSON.stringify(e))
        },
        complete(e) {
          console.log(e)
          if (!e.errCode) {
            console.log('初始化完成')
          } else if (e.errCode == 10001) {
            uni.showToast({
              icon: 'none',
              title: '请打开手机蓝牙'
            })
          } else {
            uni.showToast({
              icon: 'none',
              title: e.errMsg
            })
          }
        }
      })
    },
    close() {
      this.btnDisabled = false
      this.btnText = '搜索设备'
      this.unmatchDeviceList = []
      this.unmatchAddress = []
      this.isConnecting = false
      this.isMatching = false
      if (this.bluetoothSocket) {
        this.bluetoothSocket.close()
      }
      this.$emit('closePrint')
    },
    // Android权限查询
    requestAndroidPermission(permissionID) {
      return new Promise((resolve, reject) => {
        plus.android.requestPermissions(
          [permissionID], // 理论上支持多个权限同时查询，但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装
          function (resultObj) {
            var result = 0
            for (var i = 0; i < resultObj.granted.length; i++) {
              var grantedPermission = resultObj.granted[i]
              console.log('已获取的权限：' + grantedPermission)
              result = 1
            }
            for (var i = 0; i < resultObj.deniedPresent.length; i++) {
              var deniedPresentPermission = resultObj.deniedPresent[i]
              console.log('拒绝本次申请的权限：' + deniedPresentPermission)
              result = 0
            }
            for (var i = 0; i < resultObj.deniedAlways.length; i++) {
              var deniedAlwaysPermission = resultObj.deniedAlways[i]
              console.log('永久拒绝申请的权限：' + deniedAlwaysPermission)
              result = -1
            }
            resolve(result)
            // // 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限
            // if (result != 1) {
            //   console.log("跳转到设置")
            //   // Toast('打印需要位置权限，正在跳转到设置界面...');
            //   this.gotoAppPermissionSetting()
            // }
          },
          function (error) {
            console.log('申请权限错误：' + error.code + ' = ' + error.message)
            resolve({
              code: error.code,
              message: error.message
            })
          }
        )
      })
    },
    gotoAppPermissionSetting() {
      // console.log(plus.device.vendor);
      var Intent = plus.android.importClass('android.content.Intent')
      var Settings = plus.android.importClass('android.provider.Settings')
      var Uri = plus.android.importClass('android.net.Uri')
      var mainActivity = plus.android.runtimeMainActivity()
      var intent = new Intent()
      intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
      var uri = Uri.fromParts('package', mainActivity.getPackageName(), null)
      intent.setData(uri)
      mainActivity.startActivity(intent)
    },
    handlePrint(mac_address, index) {
      console.log('打印：', this.isConnecting)
      if (this.isConnecting) {
        return
      }
      this.isConnecting = true
      console.log('准备连接设备：', mac_address)
      if (!mac_address) {
        this.$toast('请选择打印机')
        return
      }
      this.main = plus.android.runtimeMainActivity()
      this.BluetoothAdapter = plus.android.importClass(
        'android.bluetooth.BluetoothAdapter'
      )
      let UUID = plus.android.importClass('java.util.UUID')
      this.uuid = UUID.fromString('00001101-0000-1000-8000-00805F9B34FB')
      this.BAdapter = this.BluetoothAdapter.getDefaultAdapter()
      this.device = this.BAdapter.getRemoteDevice(mac_address)
      plus.android.importClass(this.device)
      this.bluetoothSocket =
        this.device.createInsecureRfcommSocketToServiceRecord(this.uuid)
      plus.android.importClass(this.bluetoothSocket)
      if (!this.bluetoothSocket.isConnected()) {
        console.log('检测到设备未连接，尝试连接....')
        this.matchDeviceList[index].isConnecting = true
        this.matchDeviceList[index].isConnected = false
        console.log(this.matchDeviceList)
        console.log(this.matchDeviceList[index])
        console.log('连接中...')
        this.bluetoothSocket.connect()
      }
      if (this.lastIndex != -1) {
        //关闭上个连接设备
        this.matchDeviceList[this.lastIndex].isConnecting = false
        this.matchDeviceList[this.lastIndex].isConnected = false
      }
      this.isConnecting = false
      this.matchDeviceList[index].isConnecting = false
      this.matchDeviceList[index].isConnected = true
      this.lastIndex = index
      console.log('设备已连接')
      localStorage.setItem('lastConnectAddress', mac_address)
      if (this.bluetoothSocket.isConnected()) {
        console.log('test begin')
        // TestDemo  = plus.android.importClass("com.topband.TestDemo");
        let outputStream = this.bluetoothSocket.getOutputStream()
        console.log('outputStream:%o', outputStream)
        plus.android.importClass(outputStream)
        this.printValue.forEach((item) => {
          if (this.device) {
            console.log('this.BleDevice.getName():%o', this.device.getName())
          }
          let bytes = plus.android.invoke(item, 'getBytes', 'GB2312')
          // let bytes = plus.android.invoke(item, 'getBytes', 'gbk')
          outputStream.write(bytes)
          outputStream.flush()
        })
        this.device = null //这里关键
        this.bluetoothSocket.close() //必须关闭蓝牙连接否则意外断开的话打印错误
      }
    },
    /**
     *
     * @param {string} address 设备地址
     * @param {string} index 设备索引
     */
    async searchDevices(address, index) {
      console.log('address:' + address)
      if (!address) {
        //点击搜索设备按钮  清空 重新搜索
        this.matchAddress = []
        this.unmatchAddress = []
        this.unmatchDeviceList = [] //清空容器
        this.matchDeviceList = [] //清空容器
        this.isConnecting = false
        this.isMatching = false
        this.btnDisabled = true
        this.btnText = '正在搜索请稍候...'
      } else if (this.isMatching) {
        //正在配对
        return
      } else {
        //开始配对设备
        this.isMatching = true
        this.unmatchDeviceList[index].isConnecting = true
      }
      //注册类
      let _this = this
      let main = plus.android.runtimeMainActivity()
      //check location permission
      let promiseV = await this.requestAndroidPermission(
        'android.permission.ACCESS_COARSE_LOCATION'
      )
      console.log('promiseV:%o', promiseV)
      // 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限
      if (promiseV != 1) {
        console.log('跳转到设置')
        // Toast('打印需要位置权限，正在跳转到设置界面...');
        plus.nativeUI.toast('打印需要位置权限，正在跳转到设置界面')
        this.gotoAppPermissionSetting()
        _this.btnDisabled = false
        _this.btnText = '搜索设备'
        return
      }
      let IntentFilter = plus.android.importClass(
        'android.content.IntentFilter'
      )
      let BluetoothAdapter = plus.android.importClass(
        'android.bluetooth.BluetoothAdapter'
      )
      let BluetoothDevice = plus.android.importClass(
        'android.bluetooth.BluetoothDevice'
      )
      let BAdapter = BluetoothAdapter.getDefaultAdapter()
      let filter = new IntentFilter()
      let bdevice = new BluetoothDevice()
      let on = null
      let un = null
      BAdapter.startDiscovery() //开启搜索
      let receiver
      receiver = plus.android.implements(
        'io.dcloud.android.content.BroadcastReceiver',
        {
          onReceive: function (context, intent) {
            //实现onReceiver回调函数
            plus.android.importClass(intent) //通过intent实例引入intent类，方便以后的‘.’操作
            console.log(intent.getAction()) //获取action
            if (
              intent.getAction() ==
              'android.bluetooth.adapter.action.DISCOVERY_FINISHED'
            ) {
              main.unregisterReceiver(receiver) //取消监听
              _this.btnDisabled = false
              _this.btnText = '搜索设备'
              console.log('搜索结束')
            } else {
              _this.BleDevice = intent.getParcelableExtra(
                BluetoothDevice.EXTRA_DEVICE
              )
              //判断是否配对
              console.log('bledevice:' + _this.BleDevice)
              if (
                _this.BleDevice &&
                _this.BleDevice.getBondState() == bdevice.BOND_NONE
              ) {
                console.log(
                  '蓝牙设备：' +
                    _this.BleDevice.getName() +
                    '    ' +
                    _this.BleDevice.getAddress()
                )
                //参数如果跟取得的mac地址一样就配对
                if (address == _this.BleDevice.getAddress()) {
                  console.log('开始配对-------------')
                  if (_this.BleDevice.createBond()) {
                    //配对命令.createBond()
                    console.log('配对成功:', _this.BleDevice.createBond())
                    let obj = {
                      id: _this.BleDevice.getAddress(),
                      name: _this.BleDevice.getName(),
                      isConnecting: false,
                      isConnected: false
                    }
                    _this.isMatching = false
                    _this.unmatchDeviceList.splice(index, 1)
                    if (_this.matchAddress.indexOf(obj.id) == -1) {
                      _this.matchAddress.push(obj.id)
                      _this.matchDeviceList.push(obj)
                    }
                    // this.listenerConnection()
                  } else {
                    console.log('配对失败:', _this.BleDevice.createBond())
                    _this.isMatching = false
                    _this.unmatchDeviceList[index].isConnecting = false
                  }
                } else {
                  console.log(
                    '未配对蓝牙设备：' +
                      _this.BleDevice.getName() +
                      '    ' +
                      _this.BleDevice.getAddress()
                  )
                  if (_this.BleDevice.getName() != on) {
                    //判断防止重复添加
                    let obj = {
                      id: _this.BleDevice.getAddress(),
                      name: _this.BleDevice.getName(),
                      isConnecting: false,
                      isConnected: false
                    }
                    if (_this.unmatchAddress.indexOf(obj.id) == -1) {
                      _this.unmatchAddress.push(obj.id)
                      _this.unmatchDeviceList.push(obj)
                    }
                  }
                }
              } else {
                if (_this.BleDevice.getName() != un) {
                  //判断防止重复添加
                  console.log(
                    '已配对蓝牙设备：' +
                      _this.BleDevice.getName() +
                      '    ' +
                      _this.BleDevice.getAddress()
                  )
                  let obj = {
                    id: _this.BleDevice.getAddress(),
                    name: _this.BleDevice.getName(),
                    isConnecting: false,
                    isConnected: false
                  }
                  if (_this.matchAddress.indexOf(obj.id) == -1) {
                    _this.matchAddress.push(obj.id)
                    _this.matchDeviceList.push(obj)
                  }
                }
              }
            }
          }
        }
      )
      filter.addAction(bdevice.ACTION_FOUND)
      filter.addAction(BAdapter.ACTION_DISCOVERY_STARTED)
      filter.addAction(BAdapter.ACTION_DISCOVERY_FINISHED)
      filter.addAction(BAdapter.ACTION_STATE_CHANGED)
      main.registerReceiver(receiver, filter) //注册监听
    }
  }
}
</script>

<style scoped lang="scss">
.print-wrap {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: rgba(0, 0, 0, 0.8);
  z-index: 1000;
}
.print-main {
  width: 80%;
  padding: 20px 10px;
  background-color: #fff;
  border-radius: 10px;
}
.btn-wrap {
  display: flex;
  justify-content: space-between;
}
li {
  margin: 8px 0;
}
button {
  height: 32px;
}
#unmatchDevice,
#matchDevice {
  max-height: 200px;
  overflow: auto;
}
#matchDevice li.isConnected {
  color: #1989fa;
}
.btn-info {
  padding: 0 15px;
  border-radius: 2px;
  font-size: 14px;
  color: #fff;
  background-color: #1989fa;
  border: 1px solid #1989fa;
}
.btn-info.plain {
  color: #1989fa;
  background-color: #fff;
}
.btn-info:disabled {
  background-color: #005ea7;
}
#unmatchDevice .van-cell,
#matchDevice .van-cell {
  padding: 8px 16px 8px 8px;
}
#matchDevice .van-loading__spinner,
#unmatchDevice .van-loading__spinner {
  width: auto;
  height: 100%;
}
.van-icon-success {
  color: #2753f5;
}
</style>
<style>
#unmatchDevice li,
#matchDevice li {
  margin: 8px 0;
}
</style>
